package experiment;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;

import application.FuzzyMath;

import vo.User;
import Utils.Constants;
import Utils.FileUtils;
import Utils.MathUtils;
import Utils.SortUtils;
import dao.UserDao;

public class Evaluation {

	// 取borda排序的topN来标注，人工标注的时候采样用
	public static void genHumanTag(int topN, int order, String sourceFile, String targetFile) {
		Hashtable<String, Double> userId_borda = FileUtils.readHashtableD(sourceFile);
		Map.Entry[] entries = SortUtils.sortedHashtableByValue(userId_borda, order);
		String content = "";
		for (int i = 0; i < topN; i++) {
			String userId = (String) entries[i].getKey();
			String username = UserDao.getById(userId).getName();
			System.out.println(username);
			content += "#" + userId + "#" + username + "\n";
		}
		FileUtils.write(targetFile, content);
	}

	// 读取human tag文件，只剩userId_tag的hash
	public static Hashtable<String, Double> readHumanTag(String fileName) {
		Hashtable<String, Double> userId_tag = new Hashtable<String, Double>();
		String fileContent = FileUtils.readFile(fileName, "utf-8");
		String lines[] = fileContent.split("\n");
		int i = 0;
		for (String line : lines) {
			String items[] = line.split(Constants.HASH_SEPERATOR);
			i++;
			userId_tag.put(items[1], Double.parseDouble(items[0]));
		}
		return userId_tag;
	}

	// 计算标注list和计算出的list的评价值
	// 参数是topN
	public static void computePRF_TopN(Hashtable<String, Double> userId_borda, Hashtable<String, Double> userId_tag) {

		String result = "";
		for (Constants.topN = 10; Constants.topN < 200; Constants.topN += 10) {
			double p = computePRF(userId_borda, userId_tag);
			result += Constants.topN + "#" + p + "\n";
			System.out.println(Constants.topN + "#" + p);
		}
		FileUtils.write("topN_p.txt", result);
	}

	// 计算标注list和计算出的list的评价值
	// 参数是topN
	public static double computePRF(Hashtable<String, Double> userId_borda, Hashtable<String, Double> userId_tag) {

		Map.Entry[] entries = SortUtils.sortedHashtableByValue(userId_borda, Constants.DESC);
		// for (int topN = 10; topN < 200; topN = topN + 10) {
		int topMCount = 0;// 结果中topN中的media的数
		int topNMCount = 0;// 结果中topN中的非media个数
		int bottomMCount = 0;// 排名之后的
		int bottomNMCount = 0;// 排名之后的
		for (int i = 0; i < userId_tag.size(); i++) {
			String key = (String) entries[i].getKey();
			Double tag = userId_tag.get(key);
			if (i < Constants.topN) {
				if (tag == 1)
					topMCount++;
				else if (tag == 0)
					topNMCount++;
			} else {
				if (tag == 1.0)
					bottomMCount++;
				else if (tag == 0)
					bottomNMCount++;
			}

		}

		// 计算PRF
		double precision = MathUtils.precision((double) topMCount / (Constants.topN), 3);
		// double recall = MathUtils.precision((double) topMCount / (topMCount +
		// bottomMCount), 3);
		// double f = MathUtils.precision(2 * precision * recall / (precision +
		// recall), 3);

		return precision;
	}

	// 计算P最大的时候的各个权重的值
	public static void OptimizaWeights() {
		// 计算能力值，分别排名，写入文件
		FuzzyMath.computeBordaScore();

		// load 实验用户，还有用户的标注
		ArrayList<String> userIds = Init.loadUserIds();
		Hashtable<String, Double> userId_tag = readHumanTag(Constants.HUMAN_TAG_PATH);
		double a = 1;
		double b = 1;
		double c = 1;
		double d = 1;
		double maxP = 0;// 因为概率是0-1之间的
		double minP = 1;
		String max = "";
		String min = "";
		int ceiling = 10;
		String content = "";
		for (a = 1; a < ceiling; a++) {
			for (b = 1; b < ceiling; b++) {
				for (c = 1; c < ceiling; c++) {
					for (d = 1; d < ceiling; d++) {
						// 计算borda值的排序结果
						Hashtable<String, Double> userId_borda = FuzzyMath.bordaRanking(a, b, c, d, userIds);
						double p = computePRF(userId_borda, userId_tag);
						content += a + "_" + b + "_" + c + "_" + d + ":" + p + "\n";
						System.out.println("p:" + p);
						if (p > maxP) {
							maxP = p;
							max = a + "_" + b + "_" + c + "_" + d;
						}
						if (p < minP) {
							minP = p;
							min = a + "_" + b + "_" + c + "_" + d;
						}

					}
				}
			}
		}
		System.out.println("maxP:" + maxP);
		System.out.println("minP:" + minP);
		System.out.println("max:" + max);
		System.out.println("min:" + min);
		FileUtils.write("prf_results.txt", content);

	}

	public static void genUserIds(String fileName) {
		String fileContent = FileUtils.readFile(fileName, "utf-8");
		String lines[] = fileContent.split(Constants.LINE_SEPERATOR);
		String result = "";
		for (String line : lines) {
			String items[] = line.split(Constants.HASH_SEPERATOR);
			result += items[1] + Constants.LINE_SEPERATOR;
		}
		FileUtils.write(Constants.USERID_PATH, result);
	}

	public static void isBalanced(String fileName) {
		String fileContent = FileUtils.readFile(fileName, "utf-8");
		String lines[] = fileContent.split(Constants.LINE_SEPERATOR);
		int positive = 0;
		int negative = 0;
		for (String line : lines) {
			String items[] = line.split(Constants.HASH_SEPERATOR);
			if (items[0].equals("0"))
				negative++;
			else
				positive++;
		}
		System.out.println("positive:" + positive);
		System.out.println("negative:" + negative);
	}

	// 计算权重变化对P的影响
	public static void computeWeightPrecision() {
		String fileContent = FileUtils.readFile("prf_results.txt", "utf-8");
		System.out.println(fileContent);
		// 算a的
		String contentA = "";
		String contentB = "";
		String contentC = "";
		String contentD = "";
		String lines[] = fileContent.split(Constants.LINE_SEPERATOR);
		for (String line : lines) {
			String items[] = line.split(":");
			double p = Double.parseDouble(items[1]);
			String weights[] = items[0].split("_");
			String a = weights[0];
			String b = weights[1];
			String c = weights[2];
			String d = weights[3];
			System.out.println(a + "," + b + "," + c + "," + d);
			if (b.equals("2.0") && c.equals("1.0") && d.equals("5.0")) {
				contentA += a + Constants.HASH_SEPERATOR + p + Constants.LINE_SEPERATOR;
			}
			if (a.equals("2.0") && c.equals("1.0") && d.equals("5.0")) {
				contentB += b + Constants.HASH_SEPERATOR + p + Constants.LINE_SEPERATOR;
			}
			if (a.equals("2.0") && b.equals("2.0") && d.equals("5.0")) {
				contentC += c + Constants.HASH_SEPERATOR + p + Constants.LINE_SEPERATOR;
			}
			if (a.equals("2.0") && b.equals("2.0") && c.equals("1.0")) {
				contentD += d + Constants.HASH_SEPERATOR + p + Constants.LINE_SEPERATOR;
			}
		}
		FileUtils.write("a_p.txt", contentA);
		FileUtils.write("b_p.txt", contentB);
		FileUtils.write("c_p.txt", contentC);
		FileUtils.write("d_p.txt", contentD);
	}

	public static void getUnTagged() {
		String tagged = FileUtils.readFile("human_tag_ranking.txt", "utf-8");
		String raw = FileUtils.readFile("human_tag_ranking.txt", "utf-8");
		String tagged_lines[] = tagged.split(Constants.LINE_SEPERATOR);
		String raw_lines[] = raw.split(Constants.LINE_SEPERATOR);
		for (String tLine : tagged_lines) {
			String tUserId = tLine.split("#")[1];
			if (!Arrays.asList(raw_lines).contains(tUserId))
				System.out.println();
		}
	}

	public static void main(String args[]) {
		// (1)权重确定的实验
		// 1. 生成需要人工标注的用户列表
		// genHumanTag(600, Constants.DESC,
		// "1_1_1_1_borda.txt",Constants.HUMAN_TAG_PATH);

		// 2. 抽取出标记的ids
		// genUserIds(Constants.HUMAN_TAG_PATH);

		// 3.为列表用户算各种ranking

		// 4.计算weights

//		 OptimizaWeights();

		// 计算权重对结果的影响
		// computeWeightPrecision();

		// （2）排序的实验
		Hashtable<String, Double> userId_tag = readHumanTag(Constants.HUMAN_TAG_PATH);
		Hashtable<String, Double> userId_borda = FileUtils.readHashtableD("borda_ranking_2.0_2.0_1.0_5.0.txt");
		computePRF_TopN(userId_borda, userId_tag);

		// 如果需要重新标注再标注
		// genHumanTag(200, Constants.DESC, "borda_ranking_2.0_2.0_1.0_5.0.txt",
		// "human_tag_raw.txt");
		// getUnTagged();
	}
}
